#include "stdafx.h"

#include "Utility.h"
#include <sys/stat.h>
#include <io.h>
#include <tchar.h>
#include <wchar.h>
#include <shlobj.h>
#include <time.h>

#include "stdmylog.h"

inline void strncpy_z(char* pDest, const char* pSrc, int nLength)
{
	strncpy(pDest, pSrc, nLength);
	pDest[nLength-1] = 0;
}
int GetVPUID()
{
	HKEY hKey = NULL;
	if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\services\\WSPSI\\Parameters"), 0, KEY_READ, &hKey))
	{
		DWORD cbData;
		DWORD dwRet;

		TCHAR szPath[MAX_PATH] = _T("");
		cbData = MAX_PATH;
		
		//printf("\nRetrieving the data...");
		
		DWORD dwType = REG_DWORD;
		DWORD dwValue = 0;
		DWORD dwSize = sizeof(DWORD);
		dwRet = RegQueryValueEx( hKey,
			TEXT("dwVpuId"),
			NULL,
			NULL,
			(LPBYTE)&dwValue,
			&dwSize );

		RegCloseKey(hKey);
		return dwValue;
	}
	return 0;
}

char* GetWSPConfig(char* szConfig, int nSize)
{
	if( nSize <= 0 )
		return NULL;

#ifdef TRYINTEST
	{
		TCHAR tch[MAX_PATH];
		GetModuleFileName(NULL,tch,MAX_PATH);
		_tcscat(tch,_T(".ini"));
		if(IsFileExist(tch)){
			strncpy_z(szConfig, tch, nSize);
			return szConfig;
		}
	}
#endif

	HKEY hKey = NULL;
	if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\QESystem\\Parameters"), 0, KEY_READ, &hKey))
	{
		DWORD cbData;
		DWORD dwRet;

		TCHAR szPath[MAX_PATH] = _T("");
		cbData = MAX_PATH;
		
		//printf("\nRetrieving the data...");
		
		dwRet = RegQueryValueEx( hKey,
			TEXT("ConfigFile"),
			NULL,
			NULL,
			(LPBYTE)szPath,
			&cbData );

		RegCloseKey(hKey);
		strncpy_z(szConfig, szPath, nSize);
		return szConfig;
	}

	strcpy_s(szConfig, sizeof(szConfig), "");
	return szConfig;
}



TCHAR RECONCILE_FLAG[MAX_PATH] = _T("Reconcile");
void WriteReconcileFlag()
{
	HKEY hKey = NULL;
	if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ | KEY_WRITE, &hKey))
	{
		DWORD cbData;
		DWORD dwRet;

		TCHAR szPath[MAX_PATH] = _T("1");
		cbData = MAX_PATH;
		
		//printf("\nRetrieving the data...");
		
		dwRet = RegSetValueEx( hKey,
			RECONCILE_FLAG,
			NULL,
			REG_SZ,
			(LPBYTE)szPath,
			cbData );

		RegCloseKey(hKey);
	}
}

void ClearReconcileFlag()
{
	HKEY hKey = NULL;
	if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ | KEY_WRITE, &hKey))
	{
		RegDeleteValue(hKey, RECONCILE_FLAG);
		RegCloseKey(hKey);
	}
}

bool ReadyToReconcile()
{
	HKEY hKey = NULL;//ERROR_FILE_NOT_FOUND
	if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hKey))
	{
		DWORD cbData;
		DWORD dwRet;

		TCHAR szPath[MAX_PATH] = _T("");
		cbData = MAX_PATH;
		
		DWORD dwType = REG_SZ;
		dwRet = RegQueryValueEx( hKey,
			RECONCILE_FLAG,
			NULL,
			&dwType,
			(LPBYTE)szPath,
			&cbData );

		RegCloseKey(hKey);
		if (_tcscmp(szPath, _T("1")) == 0)
			return true;
		else
			return false;
	}
	return false;
}

char* GetRegistryEntry(char* szRegEntry, int nSize)
{
	if( szRegEntry == NULL || nSize <= 0 )
		return NULL;

	HKEY hKey = NULL;
	if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\WSPSI\\Parameters", 0, KEY_READ, &hKey))
	{
		DWORD cbData;
		DWORD dwRet;

		CHAR szPath[MAX_PATH] = _T("");
		cbData = MAX_PATH;
		
		dwRet = RegQueryValueEx( hKey,
			TEXT("Bridge_ConfigFile"),
			NULL,
			NULL,
			(LPBYTE)szPath,
			&cbData );

		RegCloseKey(hKey);
		strncpy_z(szRegEntry, szPath, nSize);
		return szRegEntry;
	}
	strcpy_s(szRegEntry, sizeof(szRegEntry), "");
	return szRegEntry;
}

char* GetCurrentDir(const char* szCurFile, char* szCurDir, int nSize)
{
	if( szCurDir == NULL || szCurDir == NULL || nSize <= 0 )
		return NULL;

	string curFile(szCurFile);
	size_t last = curFile.find_last_of('\\');
	
	if( last != string::npos )
		curFile = curFile.substr(0, last);
	
	strncpy_z(szCurDir, szCurFile, nSize);
	return szCurDir;
}

BOOL MyGetFileTime(std::string lpFileName, LPFILETIME lpFileTime)
{
	HANDLE hFile = CreateFile(lpFileName.c_str(),  // file name 
		GENERIC_READ,                   // open for reading 
		0,                              // do not share 
		NULL,                           // default security 
		OPEN_EXISTING,                  // existing file only 
		FILE_ATTRIBUTE_NORMAL,          // normal file 
		NULL);                          // no template 
	if (hFile != INVALID_HANDLE_VALUE) 
	{
		BOOL bRet = ::GetFileTime(hFile, NULL, NULL, lpFileTime);
		::CloseHandle(hFile);
		return bRet;
	}
	return FALSE;
}

BOOL IsFileExist(const char* pszFileName)
{
	if( pszFileName == NULL)
		return FALSE;

	struct _stat buf;
    int result = _stat( pszFileName, &buf );
	if( 0== result )
	{
		if( ((buf.st_mode & _S_IFREG) ||(buf.st_mode & _S_IFDIR)) && ( buf.st_mode & _S_IREAD) )
			return TRUE;
	}
	
	return FALSE;
}

void SimpleLogInfo(LogConfig* _option, int logType, const char* pzFormat, ...)
{
	if( _option == NULL )
	{
		_option = CStdMyLog::GetInstance().DefLogConfig();
	}

	char szBuffer[8192];

	// construct the debug string
	va_list ap;
	va_start(ap, pzFormat);
	_vsnprintf(szBuffer, sizeof(szBuffer), pzFormat, ap);
	va_end(ap);

	CStdMyLog::GetInstance().OutputLog(*_option, logType, szBuffer);

	return;
} 

void LogStart(){
	CStdMyLog::GetInstance().StartRunT();
}
void LogStop(){
	CStdMyLog::GetInstance().StopRunT();
}

void DoLogInfo(LogConfig* _option, const char* pszClassFunc, int logType, const char* pzFormat, ...)
{
	if( _option == NULL )
	{
		_option = CStdMyLog::GetInstance().DefLogConfig();
	}
	if( _option->bLogAsync ) {
		CHAR szBuffer[8192];
		va_list ap;
		va_start(ap, pzFormat);
		_vsnprintf(szBuffer, sizeof(szBuffer), pzFormat, ap);
		va_end(ap);

		LogPackage msg;
		msg.m_nlogType = logType;
		strncpy(msg.m_szclass_memfunc, pszClassFunc, sizeof(msg.m_szclass_memfunc)-1);
		strncpy(msg.m_szModuleName, _option->szModuleName, sizeof(msg.m_szModuleName)-1);
		msg.m_szBuffer = szBuffer;
		memcpy(&msg.Info, _option, sizeof(msg.Info));
		msg.m_nThreadID = GetCurrentThreadId();
		::GetLocalTime(&msg.time);
		CStdMyLog::GetInstance().AddLog2Que(*_option, &msg);
	}
	else{
		string classname(pszClassFunc);
		string funcmem;
		int    nPos1     = classname.find_last_of(':');
		if( nPos1 != string::npos ) {
			funcmem      = classname.substr(nPos1+1,string::npos);
			if( nPos1-1 >= 1 )
				classname  = classname.substr(0,nPos1-1);
			else
				classname  = "";
		}
		char szBuffer[8192];
		{
			va_list ap;
			va_start(ap, pzFormat);
			_vsnprintf(szBuffer, sizeof(szBuffer), pzFormat, ap);
			va_end(ap);
			int len = strlen(szBuffer)-1;
			if(szBuffer[len]=='\n'||szBuffer[len]=='\r')
				szBuffer[len] = '\0';
		}
		CStdMyLog::GetInstance().OutputLog(*_option, classname.c_str(), funcmem.c_str(), logType, NULL, GetCurrentThreadId(), szBuffer);
	}
}
BOOL MakeLogConfig(LogConfig* _option, const char* szFilePath, int nLogLevl, int nLogViewLevl, BOOL bOutput, BOOL bOutputDebugView, BOOL bOutputFile, int LogHisLim)
{
	CStdMyLog::SetUp(*_option, szFilePath, nLogLevl,nLogViewLevl,bOutput,bOutputDebugView,bOutputFile,LogHisLim);
	return TRUE;
}
void GetDefLogConfig(LogConfig* _option)
{
	if( _option == NULL )
		return ;

	memset(_option, 0, sizeof(LogConfig));
	_option->LogHisLim = 24;
	strcpy( _option->szFileName, "c:\\");

	_option->bLogAsync   = false;
	_option->bOutput	 = true;
	_option->bOutputDebugView = true;
	_option->bOutputFile = true;
	_option->LogHisLim   = 24;
	_option->nLogLevl    = 4;
	_option->nLogViewLevl=4;
	strcpy(_option->szModuleName, "Default");
}

HANDLE MyLockFile(LPCSTR lpFileName)
{
	HANDLE hFile = CreateFile(lpFileName,  // file name 
		GENERIC_READ | GENERIC_WRITE,                   // open for reading 
		FILE_SHARE_READ,                              
		NULL,                           // default security 
		OPEN_EXISTING,                  // existing file only 
		FILE_ATTRIBUTE_NORMAL,          // normal file 
		NULL);                          // no template 
	if (hFile != INVALID_HANDLE_VALUE) 
	{
		return hFile;
	}
	return INVALID_HANDLE_VALUE;
}

void MyUnlockFile(HANDLE hFile)
{
	if (hFile != INVALID_HANDLE_VALUE) 
		CloseHandle(hFile);
}

BOOL DeleteDir(LPCSTR szPath)
{
	if (szPath == NULL || strlen(szPath) == 0)
		return FALSE;

	bool bRet = true;
	if( (GetFileAttributes(szPath)&FILE_ATTRIBUTE_DIRECTORY)!=0 )
	{
		char szTmp[MAX_PATH]="";
		WIN32_FIND_DATA fd;
		lstrcpy(szTmp,szPath);
		if(szTmp[lstrlen(szTmp)-1] != '\\')
			lstrcat(szTmp, "\\");
		lstrcat(szTmp,"*.*");
		HANDLE hd=FindFirstFile(szTmp,&fd);
		lstrcpy(szTmp,szPath);
		if(szTmp[lstrlen(szTmp)-1] != '\\')
			lstrcat(szTmp,"\\");

		if(hd != INVALID_HANDLE_VALUE)
		{
			do
			{
				lstrcpy(szTmp,szPath);
				if(szTmp[lstrlen(szTmp)-1] != '\\')
					lstrcat(szTmp,"\\");

				if( (fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)==0 )
				{
					lstrcat(szTmp,fd.cFileName);
					bRet = DeleteFile(szTmp) != 0;
					if(!bRet)
						SimpleLogInfo(NULL, LOG_ERROR, "delete file error code=%d\n",GetLastError());
				}
				else if(lstrcmp(".", fd.cFileName) != 0 && lstrcmp("..", fd.cFileName) != 0)
				{
					lstrcat(szTmp,fd.cFileName);
					bRet = DeleteDir(szTmp);
				}
				if (bRet == false)
				{
					SimpleLogInfo(NULL, LOG_TRACE,_T("Delete %s failed!"), szTmp);
					break;
				}
			}
			while(FindNextFile(hd, &fd));
			FindClose(hd);
		}
		if (bRet)
			bRet = RemoveDirectory(szPath) != 0;
		int nError = GetLastError();
		if (nError != 0)
			SimpleLogInfo(NULL, LOG_TRACE,_T("Error id = %d \n"), nError);
	}
	return bRet;
}

BOOL IsDirectory(LPCSTR strDir)
{
	char szTmp[MAX_PATH]="";
	WIN32_FIND_DATA fd;
	lstrcpy(szTmp,strDir);
	if(szTmp[lstrlen(szTmp)-1] != '\\')
		lstrcat(szTmp, "\\");
	lstrcat(szTmp,"*.*");
	HANDLE hd=FindFirstFile(szTmp,&fd);
	if (hd != INVALID_HANDLE_VALUE)
	{
		FindClose(hd);
		return true;
	}
	else
		return false;
}



// Ensures the given path exists, creating it if needed
BOOL EnsurePathExists(LPCSTR lpszPath)
{
  // Nothing to do if path already exists
  if (DirectoryExists(lpszPath))
    return true;

  // Ignore trailing backslash
  size_t nLen = _tcslen(lpszPath);
  if (lpszPath[nLen - 1] == '\\')
    nLen--;

  // Skip past drive specifier
  int nCurrLen = 0;
  if (nLen >= 3 && lpszPath[1] == ':' && lpszPath[2] == '\\')
    nCurrLen = 2;

  // We can't create root so skip past any root specifier
  while (lpszPath[nCurrLen] == '\\')
    nCurrLen++;

  // Test each component of this path, creating directories as needed
  while (nCurrLen < nLen)
  {
    // Parse next path compenent
    LPCTSTR psz = _tcschr(lpszPath + nCurrLen, '\\');
    if (psz != NULL)
      nCurrLen = (int)(psz - lpszPath);
    else
      nCurrLen = nLen;

    // Ensure this path exists
   //CString sPath;
   TCHAR sPath[MAX_PATH] = _T("");
   memcpy(sPath, lpszPath, sizeof(TCHAR) * nCurrLen);
   //sPath.SetString(lpszPath, nCurrLen);
    if (!DirectoryExists(sPath))
      if (!::CreateDirectory(sPath, NULL))
        return false;

    // Skip over current backslash
    if (lpszPath[nCurrLen] != '\0')
      nCurrLen++;
  }
  return true;
}

// Returns true if the specified path exists and is a directory
BOOL DirectoryExists(LPCSTR lpszPath)
{
  DWORD dw = ::GetFileAttributes(lpszPath);
  return (dw != INVALID_FILE_ATTRIBUTES &&
    (dw & FILE_ATTRIBUTE_DIRECTORY) != 0);
}


int GetRandNumber(int nMin, int nMax)
{
	// Seed the random-number generator with current time so that
	// the numbers will be different every time we run.
	//
	int nRealMin = nMin;
	int nRealMax = nMax;
	if (nMin < 0)
	{
		nRealMin = 0;
		nRealMax -= nMin;
	}
	static bool bSeed = false;
	if (!bSeed)
		srand( (unsigned)time( NULL ) );
	bSeed = true;

	int rand100 = (((double) rand() / 
		(double) RAND_MAX) * nRealMax + nRealMin);
	return rand100 + nMin;
}

char* GetCurTime(char* pszTime, int nSize)
{
	if( pszTime == NULL || nSize <= 0 )
		return NULL;

	SYSTEMTIME curTime;
	::GetLocalTime(&curTime);
	//prepare directories
	CHAR szFrameFolder[MAX_PATH] = _T("");
	_stprintf_s(szFrameFolder, _T("%d%02d%02d%02d%02d%02d%03d"), curTime.wYear, curTime.wMonth, curTime.wDay, curTime.wHour, curTime.wMinute, curTime.wSecond, curTime.wMilliseconds);

	strncpy_z(pszTime, szFrameFolder, nSize);
	return pszTime;
}

HANDLE MyCreateFile(
					LPCSTR lpFileName,
					DWORD dwDesiredAccess,
					DWORD dwShareMode,
					LPSECURITY_ATTRIBUTES lpSecurityAttributes,
					DWORD dwCreationDisposition,
					DWORD dwFlagsAndAttributes,
					HANDLE hTemplateFile,
					int nInterval,
					int nRetry )
{
	HANDLE hFile = INVALID_HANDLE_VALUE;
	int i = 0;

	while(( hFile == INVALID_HANDLE_VALUE) && i < nRetry)
	{
		hFile = CreateFile(	lpFileName,
			dwDesiredAccess,
			dwShareMode,
			lpSecurityAttributes,
			dwCreationDisposition,
			dwFlagsAndAttributes,
			hTemplateFile
			);
		Sleep(nInterval);
		if (i > 0)
			SimpleLogInfo(NULL, LOG_ERROR, "Retry to open file %s", lpFileName);
		i++;
	}
	return hFile;
}